#include "hardcodedFigure.h"

#include <spri/data.h>
#include <spri/assets.h>

#include <util/indexMap.h>

#include <foun/color.h>
#include <foun/debug.h>

#include <string.h>

/*
 * Internal Constants
 */
static const f32 JOINT_SIZE = 8.0f;

static const f32 THIGH_WIDTH = 16.0f;
static const f32 THIGH_LENGTH = 40.0f;
static const f32 CALF_WIDTH = 12.0f;
static const f32 CALF_LENGTH = 40.0f;
static const f32 FOOT_WIDTH = 10.0f;
static const f32 FOOT_LENGTH = 16.0f;

static const lct::foun::FloatColor LEG_JOINT_COLOR_R = { 0.0f, 0.0f, 0.5f, 1.0f };
static const lct::foun::FloatColor LEG_SHAPE_COLOR_R = { 0.0f, 0.0f, 1.0f, 1.0f };
static const lct::foun::FloatColor LEG_JOINT_COLOR_L = { 0.0f, 0.5f, 0.0f, 1.0f };
static const lct::foun::FloatColor LEG_SHAPE_COLOR_L = { 0.0f, 1.0f, 0.0f, 1.0f };

static const f32 CHEST_WIDTH = 20.0f;
static const f32 CHEST_LENGTH = 60.0f;

static const lct::foun::FloatColor TORSO_JOINT_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f };
static const lct::foun::FloatColor TORSO_SHAPE_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f };

static const f32 HEAD_WIDTH = 22.0f;
static const f32 HEAD_LENGTH = 22.0f;

static const lct::foun::FloatColor HEAD_JOINT_COLOR = { 0.5f, 0.0f, 0.5f, 1.0f };
static const lct::foun::FloatColor HEAD_SHAPE_COLOR = { 1.0f, 0.0f, 1.0f, 1.0f };

static const f32 BICEP_WIDTH = 12.0f;
static const f32 BICEP_LENGTH = 32.0f;
static const f32 FOREARM_WIDTH = 10.0f;
static const f32 FOREARM_LENGTH = 32.0f;
static const f32 HAND_WIDTH = 12.0f;
static const f32 HAND_LENGTH = 12.0f;

static const lct::foun::FloatColor ARM_JOINT_COLOR_R = { 0.5f, 0.0f, 0.0f, 1.0f };
static const lct::foun::FloatColor ARM_SHAPE_COLOR_R = { 1.0f, 0.0f, 0.0f, 1.0f };
static const lct::foun::FloatColor ARM_JOINT_COLOR_L = { 0.5f, 0.5f, 0.0f, 1.0f };
static const lct::foun::FloatColor ARM_SHAPE_COLOR_L = { 1.0f, 1.0f, 0.0f, 1.0f };

/*
 * Public Static
 */
lct::spri::FigureAsset* HardcodedFigure::BuildAsset(lct::foun::Allocator* pAllocator)
{
	static const u32 JOINT_COUNT = 15;

	lct::spri::JointData* pJointDataArray = pAllocator->AllocTypeArray<lct::spri::JointData>(JOINT_COUNT);
	{
		u32 jointIndex = 0;
		// root
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 0
			strcpy(pJointData->name, "root");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = 0.0f;
			pJointData->parentIndex = -1;
		}
		// torso
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 1
			strcpy(pJointData->name, "waist");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = 0.0f;
			pJointData->parentIndex = 0;
		}
		// head
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 2
			strcpy(pJointData->name, "neck");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = CHEST_LENGTH;
			pJointData->parentIndex = 1;
		}
		// right leg
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 3
			strcpy(pJointData->name, "hip_r");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = 0.0f;
			pJointData->parentIndex = 0;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 4
			strcpy(pJointData->name, "knee_r");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -THIGH_LENGTH;
			pJointData->parentIndex = 3;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 5
			strcpy(pJointData->name, "ankle_r");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -CALF_LENGTH;
			pJointData->parentIndex = 4;
		}
		// right arm
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 6
			strcpy(pJointData->name, "shoulder_r");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = CHEST_LENGTH;
			pJointData->parentIndex = 1;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 7
			strcpy(pJointData->name, "elbow_r");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -BICEP_LENGTH;
			pJointData->parentIndex = 6;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 8
			strcpy(pJointData->name, "wrist_r");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -FOREARM_LENGTH;
			pJointData->parentIndex = 7;
		}
		// left leg
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 9
			strcpy(pJointData->name, "hip_l");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = 0.0f;
			pJointData->parentIndex = 0;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 10
			strcpy(pJointData->name, "knee_l");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -THIGH_LENGTH;
			pJointData->parentIndex = 9;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 11
			strcpy(pJointData->name, "ankle_l");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -CALF_LENGTH;
			pJointData->parentIndex = 10;
		}
		// left arm
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 12
			strcpy(pJointData->name, "shoulder_l");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = CHEST_LENGTH;
			pJointData->parentIndex = 1;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 13
			strcpy(pJointData->name, "elbow_l");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -BICEP_LENGTH;
			pJointData->parentIndex = 12;
		}
		{
			lct::spri::JointData* pJointData = pJointDataArray + jointIndex++; // 14
			strcpy(pJointData->name, "wrist_l");
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_X] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_SCALE_Y] = 1.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_ROTATE] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_X] = 0.0f;
			pJointData->propertyArray[lct::spri::JOINT_PROPERTY_TYPE_TRANSLATE_Y] = -FOREARM_LENGTH;
			pJointData->parentIndex = 13;
		}
		LCT_ASSERT(jointIndex == JOINT_COUNT);
	}

	lct::spri::FigureAsset::Joint* pJointArray = pAllocator->AllocTypeArray<lct::spri::FigureAsset::Joint>(JOINT_COUNT);
	for (u32 jointIndex = 0; jointIndex < JOINT_COUNT; ++jointIndex) {
		lct::spri::FigureAsset::Joint* pJoint = pJointArray + jointIndex;
		lct::spri::JointData* pJointData = pJointDataArray + jointIndex;
		pJoint->pJointData = pJointData;
	}

	static const u32 PATTERN_COUNT = 3;

	lct::spri::PatternData* pPatternDataArray = pAllocator->AllocTypeArray<lct::spri::PatternData>(PATTERN_COUNT);
	{
		u32 patternIndex = 0;
		// shapes
		{
			lct::spri::PatternData* pPatternData = pPatternDataArray + patternIndex++;
			strcpy(pPatternData->name, "shape_inner"); // 0
			strcpy(pPatternData->textureTableName, "shape");
			pPatternData->propertyArray[lct::spri::PATTERN_PROPERTY_TYPE_TEXTURE_INDEX] = 0.0f;
		}
		{
			lct::spri::PatternData* pPatternData = pPatternDataArray + patternIndex++;
			strcpy(pPatternData->name, "shape_outer"); // 1
			strcpy(pPatternData->textureTableName, "shape");
			pPatternData->propertyArray[lct::spri::PATTERN_PROPERTY_TYPE_TEXTURE_INDEX] = 0.0f;
		}
		// joints
		{
			lct::spri::PatternData* pPatternData = pPatternDataArray + patternIndex++;
			strcpy(pPatternData->name, "joint"); // 2
			strcpy(pPatternData->textureTableName, "joint");
			pPatternData->propertyArray[lct::spri::PATTERN_PROPERTY_TYPE_TEXTURE_INDEX] = 0.0f;
		}
	}

	lct::spri::FigureAsset::Pattern* pPatternArray = pAllocator->AllocTypeArray<lct::spri::FigureAsset::Pattern>(PATTERN_COUNT);
	for (u32 patternIndex = 0; patternIndex < PATTERN_COUNT; ++patternIndex) {
		lct::spri::FigureAsset::Pattern* pPattern = pPatternArray + patternIndex;
		lct::spri::PatternData* pPatternData = pPatternDataArray + patternIndex;
		pPattern->pPatternData = pPatternData;
		pPattern->pTextureTableAsset = NULL;
	}

	static const u32 PART_COUNT = 29;

	lct::spri::PartData* pPartDataArray = pAllocator->AllocTypeArray<lct::spri::PartData>(PART_COUNT);
	{
		u32 partIndex = 0;
		// left leg shapes
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "thigh_l");
			pPartData->placement.width = THIGH_WIDTH;
			pPartData->placement.height = THIGH_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(THIGH_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_SHAPE_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 9;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "calf_l");
			pPartData->placement.width = CALF_WIDTH;
			pPartData->placement.height = CALF_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(CALF_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_SHAPE_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 10;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "foot_l");
			pPartData->placement.width = FOOT_LENGTH;
			pPartData->placement.height = FOOT_WIDTH;
			pPartData->placement.x = (FOOT_LENGTH / 2.0f);
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_SHAPE_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 11;
			pPartData->patternIndex = 1;
		}
		// left leg joints
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "hip_l");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_JOINT_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 9;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "knee_l");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_JOINT_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 10;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "ankle_l");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_JOINT_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 11;
			pPartData->patternIndex = 2;
		}
		// left arm shapes
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "bicep_l");
			pPartData->placement.width = BICEP_WIDTH;
			pPartData->placement.height = BICEP_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(BICEP_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_SHAPE_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 12;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "forarm_l");
			pPartData->placement.width = FOREARM_WIDTH;
			pPartData->placement.height = FOREARM_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(FOREARM_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_SHAPE_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 13;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "hand_l");
			pPartData->placement.width = HAND_WIDTH;
			pPartData->placement.height = HAND_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(HAND_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_SHAPE_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 14;
			pPartData->patternIndex = 1;
		}
		// left arm joints
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "shoulder_l");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_JOINT_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 12;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "elbow_l");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_JOINT_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 13;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "wrist_l");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_JOINT_COLOR_L, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 14;
			pPartData->patternIndex = 2;
		}
		// torso shapes
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "chest");
			pPartData->placement.width = CHEST_WIDTH;
			pPartData->placement.height = CHEST_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = (CHEST_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &TORSO_SHAPE_COLOR, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 1;
			pPartData->patternIndex = 0;
		}
		// torso joints
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "root");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &TORSO_JOINT_COLOR, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 0;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "waist");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &TORSO_JOINT_COLOR, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 1;
			pPartData->patternIndex = 2;
		}
		// head shapes
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "head");
			pPartData->placement.width = HEAD_WIDTH;
			pPartData->placement.height = HEAD_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = (HEAD_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &HEAD_SHAPE_COLOR, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 2;
			pPartData->patternIndex = 1;
		}
		// head joints
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "neck");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &HEAD_JOINT_COLOR, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 2;
			pPartData->patternIndex = 2;
		}
		// right leg shapes
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "thigh_r");
			pPartData->placement.width = THIGH_WIDTH;
			pPartData->placement.height = THIGH_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(THIGH_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_SHAPE_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 3;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "calf_r");
			pPartData->placement.width = CALF_WIDTH;
			pPartData->placement.height = CALF_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(CALF_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_SHAPE_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 4;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "foot_r");
			pPartData->placement.width = FOOT_LENGTH;
			pPartData->placement.height = FOOT_WIDTH;
			pPartData->placement.x = (FOOT_LENGTH / 2.0f);
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_SHAPE_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 5;
			pPartData->patternIndex = 1;
		}
		// right leg joints
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "hip_r");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_JOINT_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 3;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "knee_r");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_JOINT_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 4;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "ankle_r");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &LEG_JOINT_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 5;
			pPartData->patternIndex = 2;
		}
		// right arm shapes
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "bicep_r");
			pPartData->placement.width = BICEP_WIDTH;
			pPartData->placement.height = BICEP_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(BICEP_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_SHAPE_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 6;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "forarm_r");
			pPartData->placement.width = FOREARM_WIDTH;
			pPartData->placement.height = FOREARM_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(FOREARM_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_SHAPE_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 7;
			pPartData->patternIndex = 0;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "hand_r");
			pPartData->placement.width = HAND_WIDTH;
			pPartData->placement.height = HAND_LENGTH;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = -(HAND_LENGTH / 2.0f);
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_SHAPE_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 8;
			pPartData->patternIndex = 1;
		}
		// right arm joints
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "shoulder_r");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_JOINT_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 6;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "elbow_r");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_JOINT_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 7;
			pPartData->patternIndex = 2;
		}
		{
			lct::spri::PartData* pPartData = pPartDataArray + partIndex++;
			strcpy(pPartData->name, "wrist_r");
			pPartData->placement.width = JOINT_SIZE;
			pPartData->placement.height = JOINT_SIZE;
			pPartData->placement.x = 0.0f;
			pPartData->placement.y = 0.0f;
			memcpy((pPartData->propertyArray + lct::spri::PART_PROPERTY_TYPE_MODULATE_COLOR_R), &ARM_JOINT_COLOR_R, sizeof(lct::foun::FloatColor));
			pPartData->jointIndex = 8;
			pPartData->patternIndex = 2;
		}
		LCT_ASSERT(partIndex == PART_COUNT);
	}

	lct::spri::FigureAsset::Part* pPartArray = pAllocator->AllocTypeArray<lct::spri::FigureAsset::Part>(PART_COUNT);
	for (u32 partIndex = 0; partIndex < PART_COUNT; ++partIndex) {
		lct::spri::FigureAsset::Part* pPart = pPartArray + partIndex;
		lct::spri::PartData* pPartData = pPartDataArray + partIndex;
		pPart->pPartData = pPartData;
	}

	lct::spri::FigureData* pFigureData = pAllocator->AllocType<lct::spri::FigureData>();
	strcpy(pFigureData->name, "figure");
	pFigureData->jointCount = JOINT_COUNT;
	pFigureData->partCount = PART_COUNT;
	pFigureData->patternCount = PATTERN_COUNT;

	lct::spri::FigureAsset* pFigureAsset = pAllocator->AllocType<lct::spri::FigureAsset>();
	pFigureAsset->pFigureData = pFigureData;
	pFigureAsset->pPartArray = pPartArray;
	pFigureAsset->pJointArray = pJointArray;
	pFigureAsset->pPatternArray = pPatternArray;

	lct::util::StringIndexMap* pPartIndexMap = pAllocator->AllocType<lct::util::StringIndexMap>();
	for (u32 partIndex = 0; partIndex < pFigureData->partCount; ++partIndex)
	{
		lct::spri::PartData* pPartData = pPartDataArray + partIndex;

		pPartIndexMap->AddIndex(pPartData->name, partIndex, pAllocator);
	}

	pFigureAsset->pPartIndexMap = pPartIndexMap;

	lct::util::StringIndexMap* pJointIndexMap = pAllocator->AllocType<lct::util::StringIndexMap>();
	for (u32 jointIndex = 0; jointIndex < pFigureData->jointCount; ++jointIndex)
	{
		lct::spri::JointData* pJointData = pJointDataArray + jointIndex;

		pJointIndexMap->AddIndex(pJointData->name, jointIndex, pAllocator);
	}

	pFigureAsset->pJointIndexMap = pJointIndexMap;

	lct::util::StringIndexMap* pPatternIndexMap = pAllocator->AllocType<lct::util::StringIndexMap>();
	for (u32 patternIndex = 0; patternIndex < pFigureData->patternCount; ++patternIndex)
	{
		lct::spri::PatternData* pPatternData = pPatternDataArray + patternIndex;

		pPatternIndexMap->AddIndex(pPatternData->name, patternIndex, pAllocator);
	}

	pFigureAsset->pPatternIndexMap = pPatternIndexMap;

	return pFigureAsset;
}
